package com.dongbao.checkin;

import com.dongbao.data.Datacenter;
import com.dongbao.dialog.DHGToolWindow;
import com.dongbao.entity.AwardedInfo;
import com.dongbao.entity.CodeScoreInfo;
import com.dongbao.service.CodeGradeBiz;
import com.dongbao.util.CoreFileUtil;
import com.dongbao.util.IdeaApiUtil;
import com.dongbao.util.ToolWindowUtil;
import com.intellij.ide.todo.TodoFilter;
import com.intellij.notification.*;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilCore;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.util.*;

import static com.dongbao.common.AuthorityEnum.AUTHORITY_NOTIFICATION_TITLE;
import static com.dongbao.common.ScoreConstant.FULL_MARKS;


public class DHGCheckinHandlerWorker {

    private final static Logger LOG = Logger.getInstance(DHGCheckinHandlerWorker.class);

    private static final NotificationGroup NOTIFICATION_GROUP = new NotificationGroup(AUTHORITY_NOTIFICATION_TITLE, NotificationDisplayType.BALLOON, true);

    private final Project myProject;
    private final Collection<? extends Change> myChanges;
    private final TodoFilter myTodoFilter;

    private final CodeGradeBiz codeGradeBiz;

    public CodeScoreInfo allScoreInfo = new CodeScoreInfo();;

    /**
     * 当前检测到的核心文件集合
     * */
    private final Set<VirtualFile> coreFiles = new HashSet<VirtualFile>();

    /**
     * 审核通过 或者 跳过检测的文件集合
     * */
    private final Set<VirtualFile> mySkipped = new HashSet<VirtualFile>();

    public DHGCheckinHandlerWorker(@NotNull Project project, @NotNull Collection<? extends Change> changes, @Nullable TodoFilter todoFilter,@Nullable CodeGradeBiz codeGradeBiz) {
        myProject = project;
        myChanges = changes;
        myTodoFilter = todoFilter;
        this.codeGradeBiz = codeGradeBiz;

        allScoreInfo.setScore(FULL_MARKS);
    }

    public void execute() {

        /* 调用保存方法保存文件 */
        FileDocumentManager.getInstance().saveAllDocuments();
        ProgressManager.getInstance().run(new Task.Backgroundable(myProject,"提交检测代码规范", false) {
            @Override
            public void run(@NotNull ProgressIndicator indicator) {
                ApplicationManager.getApplication().runReadAction(
                        () -> {
                            runCode();
                        }
                );
            }
        });
    }

    public void runCode(){

        for (Change change : myChanges) {
            ProgressManager.checkCanceled();
            if (change.getAfterRevision() == null) continue;
            FilePath afterFilePath = change.getAfterRevision().getFile();
            VirtualFile afterFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(afterFilePath.getPath());
            String fileName = afterFilePath.getName();

            PsiFile psiFile = PsiUtilCore.getPsiFile(myProject, afterFile);
            /* 计算代码得分 */
            codeGradeBiz.calculate(afterFile,psiFile,allScoreInfo,myProject);

            /* 判断是否跳过检测 */
            for(VirtualFile skipped:mySkipped){
                if(skipped.getName().equals(fileName)){
                    /* 跳过当前文件改动的检测 */
                    continue;
                }
            }
            /* TODO: 如果当前客户端在此文件的白名单中 则跳过下面的检测步骤 (本地测试时注释)*/
//            if(CoreFileUtil.checkLeader(fileName)){
//                continue;
//            }
            try {
                /* 检查当前提交的文件是否是核心文件 */
                Boolean validationResult = CoreFileUtil.checkFile(fileName);
                /* 是核心文件,并且在git提交忽略验证文件列表中不存在(审核通过文件列表) */
                if(validationResult&&!Datacenter.auditIgnoreFiles.containsKey(fileName)){
                    /* 将这个文件添加到检测到的对象集合中 */
                    Datacenter.auditFilesContent.put(fileName,new String(afterFile.contentsToByteArray()));
                    coreFiles.add(afterFile);
                    continue;
                }
                /* 如果是核心类文件中有,又是忽略文件 则判断这个文件是否有改动,如果有改动则添加到核心文件集合中再次检测 */
                if(Datacenter.auditIgnoreFiles!=null&&validationResult&&!Datacenter.auditIgnoreFiles.get(fileName).equals(new String(afterFile.contentsToByteArray()))){
                    /* 将这个文件添加到检测到的对象集合中 */
                    Datacenter.auditFilesContent.put(fileName,new String(afterFile.contentsToByteArray()));
                    coreFiles.add(afterFile);
                    continue;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        /* 遍历得分情况 进行分数的加减 */
        List<AwardedInfo> deductions = allScoreInfo.getDeduction();
        for(AwardedInfo deduction:deductions){
            allScoreInfo.setScore(allScoreInfo.getScore() - deduction.getScore());
        }
        /* 修改代码提交时的评论,追加代码评分情况上去 */
//        IdeaApiUtil.showNotification("您最终提交代码得分:"+allScoreInfo.getScore()+"<br/><a>查看扣分项</a>", NotificationType.INFORMATION,Datacenter.project);

        DHGToolWindow fastRequestToolWindow = ToolWindowUtil.getDHGToolWindow(myProject);
        fastRequestToolWindow.refreshErrorInfos(allScoreInfo);

        NOTIFICATION_GROUP.createNotification("您最终提交代码得分:"+allScoreInfo.getScore()+"<br/><a>查看扣分项</a>", NotificationType.WARNING)
                .addAction(new NotificationAction("查看扣分项") {
                    @Override
                    public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification) {
                        /* 跳转到DHG开发工具栏的代码检测 */
                        if (fastRequestToolWindow != null) {
                            fastRequestToolWindow.skipCodeInfo();
                        }
                    }
                })
                .notify(myProject);
    }

    public Set<VirtualFile> getCoreFiles(){
        return coreFiles;
    }
}
